package com.bestcem.xm.txtanls.retry;

import com.bestcem.xm.common.core.exception.BusinessException;
import com.bestcem.xm.txtanls.grpc.client.SentimentGrpcService;
import com.zy.dp.proto.base.v1.Code;
import com.zy.dp.proto.strontium.v1.AnalyzeSentimentResponse;
import com.zy.dp.proto.strontium.v1.TextSentiment;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ArrayUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.retry.backoff.FixedBackOffPolicy;
import org.springframework.retry.policy.SimpleRetryPolicy;
import org.springframework.retry.support.RetryTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;

import static com.bestcem.xm.common.core.constant.Constants.*;

/**
 * 重试调用
 *
 * @author gy.liu
 * @version 1.0
 * @date 2021/5/17 17:27
 **/
@Slf4j
@Service
public class CallAnalysisApiSpringRetry {
    private static final Logger EMAIL_LOG = LoggerFactory.getLogger("EmailErrorLog");

    @Resource
    private SentimentGrpcService sentimentGrpcService;

    public List<TextSentiment> callApi(List<String> text, String business) {
        // 表示哪些异常需要重试,key表示异常的字节码,value为true表示需要重试
        Map<Class<? extends Throwable>, Boolean> exceptionMap = new HashMap<>(DEFAULT_MAP_SIZE);
        exceptionMap.put(Exception.class, true);
        // 构建重试模板实例
        RetryTemplate retryTemplate = new RetryTemplate();

        // 设置重试回退操作策略，主要设置重试间隔时间
        FixedBackOffPolicy backOffPolicy = new FixedBackOffPolicy();
        backOffPolicy.setBackOffPeriod(FIXED_PERIOD_TIME);

        //设置重试次数和异常类型
        SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy(MAX_RETRY_TIME, exceptionMap);

        retryTemplate.setRetryPolicy(retryPolicy);
        retryTemplate.setBackOffPolicy(backOffPolicy);

        try {
            return retryTemplate.execute(
                    // RetryCallback
                    retryContext -> {
                        if (log.isInfoEnabled()) {
                            String temp = ArrayUtils.toString(text);
                            if (temp.length() > 100) {
                                temp = temp.substring(0, 100);
                            }
                            log.info("[Txtanls] 参与训练的原话为: {}", temp);
                            log.info("[Txtanls] 参与训练的行业为: {}", business);
                        }

                        AnalyzeSentimentResponse response = sentimentGrpcService.getSentiment(text, business);
                        // 调用失败, 重试
                        if (Objects.isNull(response) || Code.ERROR.equals(response.getStatus().getCode())) {
                            String msg = Objects.isNull(response) ? "返回结果为空" : response.getStatus().getMessage();
                            throw new BusinessException(msg);
                        }
                        return response.getTextSentimentsList();
                    },

                    // RecoveryCallback
                    recoveryContext -> {
                        String errorMessage = recoveryContext.getLastThrowable().getMessage();
                        log.error("[Txtanls] Retry-大数据情感分析接口调用失败; ErrorMessage: {};", errorMessage);
                        EMAIL_LOG.error("[Txtanls] Retry-大数据情感分析接口调用失败; ErrorMessage: {};", errorMessage);
                        return null;
                    }
            );
        } catch (BusinessException e) {
            return new ArrayList<>();
        }
    }
}